package com.ybkj.daijia.api.apirest.v4up;

import com.ybkj.daijia.Setting;
import com.ybkj.daijia.serverUtils.SettingUtils;
import com.ybkj.daijia.api.beatpay.utils.BestPayCreateOrder;
import com.ybkj.daijia.api.beatpay.utils.BestPayOrderModel;
import com.ybkj.daijia.api.beatpay.utils.CryptTool;
import com.ybkj.daijia.api.member.alipay.config.AlipayConfig;
import com.ybkj.daijia.api.member.alipay.sign.MemberOrderSign;
import com.ybkj.daijia.api.member.alipay.sign.RSA;
import com.ybkj.daijia.api.member.alipay.util.AlipayNotify;
import com.ybkj.daijia.api.unionpay.AcpService;
import com.ybkj.daijia.api.unionpay.DemoBase;
import com.ybkj.daijia.api.unionpay.LogUtil;
import com.ybkj.daijia.api.unionpay.SDKConfig;
import com.ybkj.daijia.api.unionpay.SDKConstants;
import com.ybkj.daijia.api.util.ErrorConstantV4;
import com.ybkj.daijia.api.util.ResultTransport;
import com.ybkj.daijia.api.weixin.tenpayv3.Configuration;
import com.ybkj.daijia.api.weixin.tenpayv3.GetWxOrderno;
import com.ybkj.daijia.api.weixin.tenpayv3.RequestHandler;
import com.ybkj.daijia.api.weixin.tenpayv3.Sha1Util;
import com.ybkj.daijia.api.weixin.tenpayv3.TenpayUtil;
import com.ybkj.daijia.server.mc.Enterprise;
import com.ybkj.daijia.server.mc.Passenger;
import com.ybkj.daijia.server.mc.PassengerAccount;
import com.ybkj.daijia.server.sales.Coupon;
import com.ybkj.daijia.server.sales.CouponRule;
import com.ybkj.daijia.server.service.CouponService;
import com.ybkj.daijia.server.service.MemberService;
import com.ybkj.daijia.server.service.SmsService;
import com.ybkj.daijia.server.service.ZhuancheService;
import com.ybkj.daijia.server.zhuan.Order;
import com.ybkj.daijia.server.zhuan.Order.PayTypeDetails;
import com.ybkj.daijia.server.zhuan.OrderTemp;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.text.DecimalFormat;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.SortedMap;
import java.util.TreeMap;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.input.SAXBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.ApplicationEventMulticaster;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller("ZhuancheProcessControllerV4up")
@RequestMapping(value = "api/zhuanche/v4up/")
public class ZhuancheProcessControllerV4up {

    private static final Logger logger = LoggerFactory
        .getLogger(ZhuancheProcessControllerV4up.class);

    @Autowired
    private SettingUtils settingUtils;
    @Autowired
    private SmsService smsService;
    @Autowired
    private ZhuancheService zhuancheService;
    @Autowired
    private ApplicationEventMulticaster applicationEventMulticaster;
    @Autowired
    private CouponService couponService;
    @Autowired
    private MemberService memberService;

    /**
     * 获取请求参数中所有的信息
     *
     * @param request
     * @return
     */
    public static Map<String, String> getAllRequestParam(final HttpServletRequest request) {
        Map<String, String> res = new HashMap<String, String>();
        Enumeration<?> temp = request.getParameterNames();
        if (null != temp) {
            while (temp.hasMoreElements()) {
                String en = (String) temp.nextElement();
                String value = request.getParameter(en);
                res.put(en, value);
                // 在报文上送时，如果字段的值为空，则不上送<下面的处理为在获取所有参数数据时，判断若值为空，则删除这个字段>
                if (null == res.get(en) || "".equals(res.get(en))) {
                    res.remove(en);
                }
            }
        }
        return res;
    }

    // 支付宝支付前的接口
    @RequestMapping(value = "alipay/prepay")
    public @ResponseBody
    ResultTransport alipayPrepay(HttpServletResponse response,
        HttpServletRequest request, Long orderGroupId, Double amount, String groupType) {
        try {
            Setting setting = settingUtils.get();

            Map<String, Object> map = new HashMap<String, Object>();
            map.put("PartnerID", setting.getAlipayPartnerID());
            map.put("SellerID", setting.getAlipaySellerID());
            map.put("PartnerPrivKey", setting.getAlipayPartnerPrivKey());
            map.put("PartnerPublicKey", AlipayConfig.ali_public_key);
            map.put("tradeNO", "zhuanche_prepay_" + orderGroupId + "_" + groupType);// 临时表订单Id或分组id
            map.put("productName", "专车支付");
            map.put("productDescription", "专车预先支付充值");
            if (StringUtils.isNotBlank(groupType)) {
                map.put("groupType", groupType);// 一组订单支付:"group",一个订单支付:"order"
            } else {
                map.put("groupType", "order");
            }
            map.put("amount", amount);
            map.put("notifyURL", setting.getWebUrl() + "/api/zhuanche/v4up/alipay/notify");
            String content = MemberOrderSign.sign(map);
            String sign = RSA.sign(content, setting.getAlipayPartnerPrivKey(), "utf-8");
            sign = URLEncoder.encode(sign, "utf-8");
            String url = content + "&sign=\"" + sign + "\"&sign_type=\"RSA\"";

            Map<String, Object> data = new HashMap<String, Object>();
            data.put("url", url);

            ResultTransport instance = ResultTransport.getErrorBy(ErrorConstantV4.SUCCESS);
            instance.setData(data);
            return instance;
        } catch (Exception e) {
            logger.error("api zhuanche prepay 专车支付 error: {}", e);
            return ResultTransport.getErrorBy(ErrorConstantV4.SERVER_ERROR);
        }
    }

    // 支付宝支付后的接口
    @RequestMapping(value = "alipay/notify")
    public synchronized @ResponseBody
    String alipayNotify(HttpServletResponse response,
        HttpServletRequest request) throws UnsupportedEncodingException {
        Setting setting = settingUtils.get();
        // 获取支付宝POST过来反馈信息
        Map<String, String> params = new HashMap<String, String>();
        Map requestParams = request.getParameterMap();
        for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr =
                    (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
            }
            // 乱码解决，这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
            // valueStr = new String(valueStr.getBytes("ISO-8859-1"), "gbk");
            params.put(name, valueStr);
        }
        // 获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表(以下仅供参考)//
        // 商户订单号
        String out_trade_no = new String(
            request.getParameter("out_trade_no").getBytes("ISO-8859-1"),
            "UTF-8");
        // 支付宝交易号
        String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"),
            "UTF-8");
        // 交易状态
        String trade_status = new String(
            request.getParameter("trade_status").getBytes("ISO-8859-1"),
            "UTF-8");

        // 获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表(以上仅供参考)//
        logger.info("商户订单号：" + out_trade_no);
        logger.error("交易号：" + trade_no + "交易状态：" + trade_status);
        if (AlipayNotify.verify(params, setting)) {// 验证成功
            String groupType = out_trade_no.split("_")[3];
            if (trade_status.equals("TRADE_FINISHED")) {
                // 调用专车系统支付成功,把临时表的订单信息新增到真实表中
                if ("group".equals(groupType)) {// 一组订单支付完成
                    Long groupId = Long.valueOf(out_trade_no.split("_")[2]);
                    List<OrderTemp> list = zhuancheService.queryByGroupId(groupId);
                    for (OrderTemp temp : list) {
                        Coupon coupon = null;
                        if (null != temp.getCouponId()) {
                            coupon = couponService.findOne(temp.getCouponId());
                        }
                        PayTypeDetails payType = PayTypeDetails.alipay;
                        if (null != coupon) {
                            payType = Order.PayTypeDetails.coupon_alipay;
                        }
                        Order order = zhuancheService
                            .tempToForeverV4up(temp.getId(), payType, coupon);
                        if (null != order) {// 客户消费记录
                            Passenger passenger = memberService
                                .findOnePassenger(order.getPassengerId());
                            String payMemo = "订单【" + order.getOrderNo() + "】预付费使用支付宝支付"
                                + temp.getBudgetPay().setScale(2, BigDecimal.ROUND_HALF_UP)
                                .toString() + "元。";
                            if (null != coupon) {
                                if (coupon.getCouponRule().getType()
                                    .equals(CouponRule.TYPE_DEDUCTION)) {
                                    payMemo +=
                                        "并且使用了" + coupon.getCouponRule().getMoney() + "元优惠券。";
                                } else if (coupon.getCouponRule().getType()
                                    .equals(CouponRule.TYPE_DISCOUNT)) {
                                    payMemo +=
                                        "并且使用了" + coupon.getCouponRule().getDiscount() + "折优惠券。";
                                }
                            }
                            if (passenger.getType().equals(Passenger.TYPE_PASSENGER)) {
                                memberService
                                    .money(passenger, null, temp.getBudgetPay().negate(), payMemo,
                                        PassengerAccount.OPERATING_SYS,
                                        PassengerAccount.PayType.PAYTYPE_ALIPAY,
                                        order.getId(), order.getOrderNo(),
                                        PassengerAccount.ORDER_TYPE_ZHUANCHE, null,
                                        false, false);
                            } else if (passenger.getType().equals(Passenger.TYPE_ENTERPRISE)) {
                                Enterprise enterprise = memberService.findOneEnterprise(passenger
                                    .getEnterprise_id());
                                if (null != enterprise) {
                                    memberService
                                        .moneyEnterprise(enterprise, temp.getBudgetPay().negate(),
                                            payMemo,
                                            PassengerAccount.OPERATING_SYS,
                                            PassengerAccount.PayType.PAYTYPE_ALIPAY,
                                            order.getId(), order.getOrderNo(),
                                            PassengerAccount.ORDER_TYPE_ZHUANCHE,
                                            null, false, false);
                                }
                            }
                        }
                    }
                    return "success";
                } else {
                    Long orderId = Long.valueOf(out_trade_no.split("_")[2]);
                    OrderTemp temp = zhuancheService.findOneTemp(orderId);
                    if (temp.isTreatment()) {
                        return "success";
                    }
                    Coupon coupon = null;
                    if (null != temp.getCouponId()) {
                        coupon = couponService.findOne(temp.getCouponId());
                    }
                    PayTypeDetails payType = PayTypeDetails.alipay;
                    if (null != coupon) {
                        payType = Order.PayTypeDetails.coupon_alipay;
                    }
                    Order order = zhuancheService.tempToForeverV4up(orderId, payType, coupon);
                    if (null != order) {
                        // 客户消费记录
                        Passenger passenger = memberService
                            .findOnePassenger(order.getPassengerId());
                        String payMemo = "订单【" + order.getOrderNo() + "】预付费使用支付宝支付"
                            + temp.getBudgetPay().setScale(2, BigDecimal.ROUND_HALF_UP).toString()
                            + "元。";
                        if (null != coupon) {
                            if (coupon.getCouponRule().getType()
                                .equals(CouponRule.TYPE_DEDUCTION)) {
                                payMemo += "并且使用了" + coupon.getCouponRule().getMoney() + "元优惠券。";
                            } else if (coupon.getCouponRule().getType()
                                .equals(CouponRule.TYPE_DISCOUNT)) {
                                payMemo += "并且使用了" + coupon.getCouponRule().getDiscount() + "折优惠券。";
                            }
                        }
                        if (passenger.getType().equals(Passenger.TYPE_PASSENGER)) {
                            memberService
                                .money(passenger, null, temp.getBudgetPay().negate(), payMemo,
                                    PassengerAccount.OPERATING_SYS,
                                    PassengerAccount.PayType.PAYTYPE_ALIPAY,
                                    order.getId(), order.getOrderNo(),
                                    PassengerAccount.ORDER_TYPE_ZHUANCHE, null,
                                    false, false);
                        } else if (passenger.getType().equals(Passenger.TYPE_ENTERPRISE)) {
                            Enterprise enterprise = memberService
                                .findOneEnterprise(passenger.getEnterprise_id());
                            if (null != enterprise) {
                                memberService
                                    .moneyEnterprise(enterprise, temp.getBudgetPay().negate(),
                                        payMemo,
                                        PassengerAccount.OPERATING_SYS,
                                        PassengerAccount.PayType.PAYTYPE_ALIPAY,
                                        order.getId(), order.getOrderNo(),
                                        PassengerAccount.ORDER_TYPE_ZHUANCHE, null,
                                        false, false);
                            }
                        }

                        return "success";
                    } else {
                        return "fail";
                    }
                }
            } else if (trade_status.equals("TRADE_SUCCESS")) {
                // 调用专车系统支付成功,把临时表的订单信息新增到真实表中
                if ("group".equals(groupType)) {// 一组订单支付完成
                    Long groupId = Long.valueOf(out_trade_no.split("_")[2]);
                    List<OrderTemp> list = zhuancheService.queryByGroupId(groupId);
                    for (OrderTemp temp : list) {
                        Coupon coupon = null;
                        if (null != temp.getCouponId()) {
                            coupon = couponService.findOne(temp.getCouponId());
                        }
                        PayTypeDetails payType = PayTypeDetails.alipay;
                        if (null != coupon) {
                            payType = Order.PayTypeDetails.coupon_alipay;
                        }
                        Order order = zhuancheService
                            .tempToForeverV4up(temp.getId(), payType, coupon);
                        if (null != order) {
                            // 客户消费记录
                            Passenger passenger = memberService
                                .findOnePassenger(order.getPassengerId());
                            String payMemo = "订单【" + order.getOrderNo() + "】预付费使用支付宝支付"
                                + temp.getBudgetPay().setScale(2, BigDecimal.ROUND_HALF_UP)
                                .toString() + "元。";
                            if (null != coupon) {
                                if (coupon.getCouponRule().getType()
                                    .equals(CouponRule.TYPE_DEDUCTION)) {
                                    payMemo +=
                                        "并且使用了" + coupon.getCouponRule().getMoney() + "元优惠券。";
                                } else if (coupon.getCouponRule().getType()
                                    .equals(CouponRule.TYPE_DISCOUNT)) {
                                    payMemo +=
                                        "并且使用了" + coupon.getCouponRule().getDiscount() + "折优惠券。";
                                }
                            }
                            if (passenger.getType().equals(Passenger.TYPE_PASSENGER)) {
                                memberService
                                    .money(passenger, null, temp.getBudgetPay().negate(), payMemo,
                                        PassengerAccount.OPERATING_SYS,
                                        PassengerAccount.PayType.PAYTYPE_ALIPAY,
                                        order.getId(), order.getOrderNo(),
                                        PassengerAccount.ORDER_TYPE_ZHUANCHE, null,
                                        false, false);
                            } else if (passenger.getType().equals(Passenger.TYPE_ENTERPRISE)) {
                                Enterprise enterprise = memberService.findOneEnterprise(passenger
                                    .getEnterprise_id());
                                if (null != enterprise) {
                                    memberService
                                        .moneyEnterprise(enterprise, temp.getBudgetPay().negate(),
                                            payMemo,
                                            PassengerAccount.OPERATING_SYS,
                                            PassengerAccount.PayType.PAYTYPE_ALIPAY,
                                            order.getId(), order.getOrderNo(),
                                            PassengerAccount.ORDER_TYPE_ZHUANCHE,
                                            null, false, false);
                                }
                            }
                        }
                    }
                    return "success";
                } else {
                    Long orderId = Long.valueOf(out_trade_no.split("_")[2]);
                    OrderTemp temp = zhuancheService.findOneTemp(orderId);
                    if (temp.isTreatment()) {
                        return "success";
                    }
                    Coupon coupon = null;
                    if (null != temp.getCouponId()) {
                        coupon = couponService.findOne(temp.getCouponId());
                    }
                    PayTypeDetails payType = PayTypeDetails.alipay;
                    if (null != coupon) {
                        payType = Order.PayTypeDetails.coupon_alipay;
                    }
                    Order order = zhuancheService.tempToForeverV4up(orderId, payType, coupon);
                    if (null != order) {
                        // 客户消费记录
                        Passenger passenger = memberService
                            .findOnePassenger(order.getPassengerId());
                        String payMemo = "订单【" + order.getOrderNo() + "】预付费使用支付宝支付"
                            + temp.getBudgetPay().setScale(2, BigDecimal.ROUND_HALF_UP).toString()
                            + "元。";
                        if (null != coupon) {
                            if (coupon.getCouponRule().getType()
                                .equals(CouponRule.TYPE_DEDUCTION)) {
                                payMemo += "并且使用了" + coupon.getCouponRule().getMoney() + "元优惠券。";
                            } else if (coupon.getCouponRule().getType()
                                .equals(CouponRule.TYPE_DISCOUNT)) {
                                payMemo += "并且使用了" + coupon.getCouponRule().getDiscount() + "折优惠券。";
                            }
                        }
                        if (passenger.getType().equals(Passenger.TYPE_PASSENGER)) {
                            memberService
                                .money(passenger, null, temp.getBudgetPay().negate(), payMemo,
                                    PassengerAccount.OPERATING_SYS,
                                    PassengerAccount.PayType.PAYTYPE_ALIPAY,
                                    order.getId(), order.getOrderNo(),
                                    PassengerAccount.ORDER_TYPE_ZHUANCHE, null,
                                    false, false);
                        } else if (passenger.getType().equals(Passenger.TYPE_ENTERPRISE)) {
                            Enterprise enterprise = memberService
                                .findOneEnterprise(passenger.getEnterprise_id());
                            if (null != enterprise) {
                                memberService
                                    .moneyEnterprise(enterprise, temp.getBudgetPay().negate(),
                                        payMemo,
                                        PassengerAccount.OPERATING_SYS,
                                        PassengerAccount.PayType.PAYTYPE_ALIPAY,
                                        order.getId(), order.getOrderNo(),
                                        PassengerAccount.ORDER_TYPE_ZHUANCHE, null,
                                        false, false);
                            }
                        }
                        return "success";
                    } else {
                        return "fail";
                    }
                }
            }
            return "fail";
        } else {
            return "fail";
        }
    }

    // 微信支付前接口
    @RequestMapping(value = "wx/prepay")
    public @ResponseBody
    ResultTransport genpackage(HttpServletResponse response,
        HttpServletRequest request, Long orderGroupId, BigDecimal amount, String groupType) {

        Setting setting = settingUtils.get();
        String createOrderURL = Configuration.createOrderURL;

        // 商户相关资料
        String appid = setting.getWxAppID();
        String appsecret = setting.getWxAppSecret();
        String partner = setting.getWxPartnerID();
        String partnerkey = setting.getWxPartnerKey();

        // 获取openId后调用统一支付接口https://api.mch.weixin.qq.com/pay/unifiedorder
        String currTime = TenpayUtil.getCurrTime();
        // 8位日期
        String strTime = currTime.substring(8, currTime.length());
        // 四位随机数
        String strRandom = TenpayUtil.buildRandom(6) + "";
        // 10位序列号,可以自行调整。
        String strReq = strTime + strRandom;
        // 商户号
        String mch_id = partner;
        // 随机数
        String nonce_str = strReq;
        // 商品描述
        String body = "下单付费";
        // 商户订单号
        String out_trade_no = "zhuanche_prepay_" + orderGroupId + "_" + groupType;
        // 总金额以分为单位，不带小数点
        String total_fee = String.valueOf(amount.multiply(new BigDecimal(100)).intValue());
        // 订单生成的机器 IP
        String spbill_create_ip = request.getRemoteAddr();

        // 这里notify_url是 支付完成后微信发给该链接信息，可以判断会员是否支付成功，改变订单状态等。
        String notify_url = setting.getWebUrl() + "/api/zhuanche/v4up/wx/notify";

        String trade_type = "APP";

        SortedMap<String, String> packageParams = new TreeMap<String, String>();
        packageParams.put("appid", appid);
        packageParams.put("mch_id", mch_id);
        packageParams.put("nonce_str", nonce_str);
        packageParams.put("body", body);
        packageParams.put("out_trade_no", out_trade_no);
        // 这里写的金额为1 分到时修改
        // packageParams.put("total_fee", "1");
        packageParams.put("total_fee", total_fee);
        packageParams.put("spbill_create_ip", spbill_create_ip);
        packageParams.put("notify_url", notify_url);
        packageParams.put("trade_type", trade_type);

        RequestHandler reqHandler = new RequestHandler(request, response);
        reqHandler.init(appid, appsecret, partnerkey);

        String sign = reqHandler.createSign(packageParams);
        String xml = "<xml>" + "<appid>" + appid + "</appid>" + "<mch_id>" + mch_id + "</mch_id>"
            + "<nonce_str>" + nonce_str + "</nonce_str>" + "<sign>" + sign + "</sign>"
            + "<body><![CDATA[" + body + "]]></body>" + "<out_trade_no>" + out_trade_no
            + "</out_trade_no>" + "<total_fee>" + total_fee + "</total_fee>" + "<spbill_create_ip>"
            + spbill_create_ip + "</spbill_create_ip>" + "<notify_url>" + notify_url
            + "</notify_url>"
            + "<trade_type>" + trade_type + "</trade_type>" + "</xml>";

        String prepay_id = "";
        try {
            prepay_id = new GetWxOrderno().getPayNo(createOrderURL, xml);
            if (prepay_id.equals("")) {
                logger.error("统一支付接口获取预支付订单出错");
            }
        } catch (Exception e1) {
            e1.printStackTrace();
        }
        SortedMap<String, String> finalpackage = new TreeMap<String, String>();
        String timestamp = Sha1Util.getTimeStamp();
        finalpackage.put("appid", appid);
        finalpackage.put("partnerid", partner);
        finalpackage.put("prepayid", prepay_id);
        finalpackage.put("package", "Sign=WXPay");
        finalpackage.put("noncestr", nonce_str);
        finalpackage.put("timestamp", timestamp);
        String finalsign = reqHandler.createSign(finalpackage);
        finalpackage.put("sign", finalsign);
        finalpackage.put("success", Boolean.TRUE.toString());
        ResultTransport instance = ResultTransport.getErrorBy(ErrorConstantV4.SUCCESS);
        instance.setData(finalpackage);
        return instance;
    }

    // 微信支付后接口
    @RequestMapping(value = "wx/notify")
    public synchronized @ResponseBody
    String wxNotify(HttpServletResponse response,
        HttpServletRequest request) throws Exception {
        String out_trade_no = "";
        String groupType = "";
        try {
            BufferedReader br = new BufferedReader(new InputStreamReader(request.getInputStream()));
            String line = null;
            StringBuilder sb = new StringBuilder();
            while ((line = br.readLine()) != null) {
                sb.append(line);
            }
            String strxml = sb.toString();
            InputStream in = new ByteArrayInputStream(strxml.getBytes());
            SAXBuilder builder = new SAXBuilder();
            Document doc = builder.build(in);
            Element root = doc.getRootElement();
            List list = root.getChildren();
            Iterator it = list.iterator();
            while (it.hasNext()) {
                Element e = (Element) it.next();
                String k = e.getName();
                if (k.equals("out_trade_no")) {
                    out_trade_no = e.getText();
                    if (StringUtils.isNotBlank(out_trade_no)) {
                        String[] split = out_trade_no.split("_");
                        out_trade_no = split[0] + "_" + split[1] + "_" + split[2];
                        groupType = split[3];
                    }
                }
            }
            try {
                // 关闭流
                if (null != in) {
                    in.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            if (StringUtils.isBlank(out_trade_no)) {
                return "FAIL";
            }
            if ("group".equals(groupType)) {// 一组订单支付完成
                Long groupId = Long.valueOf(out_trade_no.split("_")[2]);
                List<OrderTemp> tempList = zhuancheService.queryByGroupId(groupId);
                for (OrderTemp temp : tempList) {
                    Coupon coupon = null;
                    if (null != temp.getCouponId()) {
                        coupon = couponService.findOne(temp.getCouponId());
                    }
                    PayTypeDetails payType = PayTypeDetails.weixin;
                    if (null != coupon) {
                        payType = Order.PayTypeDetails.coupon_weixin;
                    }
                    Order order = zhuancheService.tempToForeverV4up(temp.getId(), payType, coupon);
                    if (null != order) {// 客户消费记录
                        Passenger passenger = memberService
                            .findOnePassenger(order.getPassengerId());
                        String payMemo = "订单【" + order.getOrderNo() + "】预付费使用微信支付"
                            + temp.getBudgetPay().setScale(2, BigDecimal.ROUND_HALF_UP).toString()
                            + "元。";
                        if (null != coupon) {
                            if (coupon.getCouponRule().getType()
                                .equals(CouponRule.TYPE_DEDUCTION)) {
                                payMemo += "并且使用了" + coupon.getCouponRule().getMoney() + "元优惠券。";
                            } else if (coupon.getCouponRule().getType()
                                .equals(CouponRule.TYPE_DISCOUNT)) {
                                payMemo += "并且使用了" + coupon.getCouponRule().getDiscount() + "折优惠券。";
                            }
                        }
                        if (passenger.getType().equals(Passenger.TYPE_PASSENGER)) {
                            memberService
                                .money(passenger, null, temp.getBudgetPay().negate(), payMemo,
                                    PassengerAccount.OPERATING_SYS,
                                    PassengerAccount.PayType.PAYTYPE_WEIXIN,
                                    order.getId(), order.getOrderNo(),
                                    PassengerAccount.ORDER_TYPE_ZHUANCHE, null,
                                    false, false);
                        } else if (passenger.getType().equals(Passenger.TYPE_ENTERPRISE)) {
                            Enterprise enterprise = memberService
                                .findOneEnterprise(passenger.getEnterprise_id());
                            if (null != enterprise) {
                                memberService
                                    .moneyEnterprise(enterprise, temp.getBudgetPay().negate(),
                                        payMemo,
                                        PassengerAccount.OPERATING_SYS,
                                        PassengerAccount.PayType.PAYTYPE_WEIXIN,
                                        order.getId(), order.getOrderNo(),
                                        PassengerAccount.ORDER_TYPE_ZHUANCHE, null,
                                        false, false);
                            }
                        }
                    }
                }
                return "SUCCESS";
            } else {
                Long orderId = Long.valueOf(out_trade_no.split("_")[2]);
                OrderTemp temp = zhuancheService.findOneTemp(orderId);
                if (temp.isTreatment()) {
                    return "SUCCESS";
                }
                Coupon coupon = null;
                if (null != temp.getCouponId()) {
                    coupon = couponService.findOne(temp.getCouponId());
                }
                PayTypeDetails payType = PayTypeDetails.weixin;
                if (null != coupon) {
                    payType = Order.PayTypeDetails.coupon_weixin;
                }
                Order order = zhuancheService.tempToForeverV4up(orderId, payType, coupon);
                if (null != order) { // 客户消费记录
                    Passenger passenger = memberService.findOnePassenger(order.getPassengerId());
                    String payMemo = "订单【" + order.getOrderNo() + "】预付费使用微信支付"
                        + temp.getBudgetPay().setScale(2, BigDecimal.ROUND_HALF_UP).toString()
                        + "元。";
                    if (null != coupon) {
                        if (coupon.getCouponRule().getType().equals(CouponRule.TYPE_DEDUCTION)) {
                            payMemo += "并且使用了" + coupon.getCouponRule().getMoney() + "元优惠券。";
                        } else if (coupon.getCouponRule().getType()
                            .equals(CouponRule.TYPE_DISCOUNT)) {
                            payMemo += "并且使用了" + coupon.getCouponRule().getDiscount() + "折优惠券。";
                        }
                    }
                    if (passenger.getType().equals(Passenger.TYPE_PASSENGER)) {
                        memberService.money(passenger, null, temp.getBudgetPay().negate(), payMemo,
                            PassengerAccount.OPERATING_SYS, PassengerAccount.PayType.PAYTYPE_WEIXIN,
                            order.getId(), order.getOrderNo(), PassengerAccount.ORDER_TYPE_ZHUANCHE,
                            null,
                            false, false);
                    } else if (passenger.getType().equals(Passenger.TYPE_ENTERPRISE)) {
                        Enterprise enterprise = memberService
                            .findOneEnterprise(passenger.getEnterprise_id());
                        if (null != enterprise) {
                            memberService
                                .moneyEnterprise(enterprise, temp.getBudgetPay().negate(), payMemo,
                                    PassengerAccount.OPERATING_SYS,
                                    PassengerAccount.PayType.PAYTYPE_WEIXIN,
                                    order.getId(), order.getOrderNo(),
                                    PassengerAccount.ORDER_TYPE_ZHUANCHE, null,
                                    false, false);
                        }
                    }

                    return "SUCCESS";
                } else {
                    return "FAIL";
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
            return "FAIL";
        }
    }

    // 余额签单支付
    @RequestMapping(value = "balancesignPay", method = RequestMethod.POST)
    public @ResponseBody
    ResultTransport balancesignPay(Long orderGroupId, Long passengerId,
        String payType, String groupType) {
        Map<String, Object> map = new HashMap<String, Object>();
        if (!"balance".equals(payType) && !"sign".equals(payType)) {
            return ResultTransport.getErrorBy(ErrorConstantV4.PAY_TYPE_ERROR);
        }
        if ("group".equals(groupType)) {// 一组订单支付完成
            List<OrderTemp> list = zhuancheService.queryByGroupId(orderGroupId);
            for (OrderTemp temp : list) {
                if (temp.isTreatment()) {
                    return ResultTransport.getErrorBy(ErrorConstantV4.ALREADY_PAY);
                }
                Passenger passenger = memberService.findOnePassenger(passengerId);
                if (null == passenger) {
                    return ResultTransport.getErrorBy(ErrorConstantV4.PASSENGER_NOT_EXISTS);
                }
                if ("sign".equals(payType)) {
                    if (!passenger.isAllowOverdraw()) {
                        return ResultTransport.getErrorBy(ErrorConstantV4.PASSENGER_NOT_ALLOW_SIGN);
                    }
                } else if ("balance".equals(payType)) {
                    if (passenger.getType().equals(Passenger.TYPE_PASSENGER)) {
                        if (passenger.getDrawMoney().doubleValue() < temp.getBudgetPay()
                            .doubleValue()) {
                            return ResultTransport
                                .getErrorBy(ErrorConstantV4.PASSENGER_MONEY_NOT_ENOUGH);
                        }
                    } else if (passenger.getType().equals(Passenger.TYPE_ENTERPRISE)) {
                        Enterprise enterprise = memberService
                            .findOneEnterprise(passenger.getEnterprise_id());
                        if (enterprise.getDrawMoney().doubleValue() < temp.getBudgetPay()
                            .doubleValue()) {
                            return ResultTransport
                                .getErrorBy(ErrorConstantV4.PASSENGER_MONEY_NOT_ENOUGH);
                        }
                    }
                }
                PayTypeDetails prePayType = null;
                Coupon coupon = null;
                if (null != temp.getCouponId()) {
                    coupon = couponService.findOne(temp.getCouponId());
                }
                if (null != coupon) {
                    if ("sign".equals(payType)) {
                        prePayType = Order.PayTypeDetails.coupon_sign;
                    } else if ("balance".equals(payType)) {
                        prePayType = Order.PayTypeDetails.coupon_balance;
                    }
                } else {
                    if ("sign".equals(payType)) {
                        prePayType = Order.PayTypeDetails.sign;
                    } else if ("balance".equals(payType)) {
                        prePayType = Order.PayTypeDetails.balance;
                    }
                }
                Order order = zhuancheService.tempToForeverV4up(temp.getId(), prePayType, coupon);

                if (null != order) {
                    // 客户减钱，客户消费记录
                    PassengerAccount.PayType ptype = null;
                    String payMemo = "";
                    if ("sign".equals(payType)) {
                        ptype = PassengerAccount.PayType.PAYTYPE_SIGN;
                        payMemo += "订单【" + order.getOrderNo() + "】预付费使用签单支付"
                            + temp.getBudgetPay().setScale(2, BigDecimal.ROUND_HALF_UP).toString()
                            + "元。";
                    } else if ("balance".equals(payType)) {
                        ptype = PassengerAccount.PayType.PAYTYPE_BALANCE;
                        payMemo += "订单【" + order.getOrderNo() + "】预付费使用余额支付"
                            + temp.getBudgetPay().setScale(2, BigDecimal.ROUND_HALF_UP).toString()
                            + "元。";
                    }
                    if (null != coupon) {
                        if (coupon.getCouponRule().getType().equals(CouponRule.TYPE_DEDUCTION)) {
                            payMemo += "并且使用了" + coupon.getCouponRule().getMoney() + "元优惠券。";
                        } else if (coupon.getCouponRule().getType()
                            .equals(CouponRule.TYPE_DISCOUNT)) {
                            payMemo += "并且使用了" + coupon.getCouponRule().getDiscount() + "折优惠券。";
                        }
                    }
                    if (passenger.getType().equals(Passenger.TYPE_PASSENGER)) {
                        memberService.money(passenger, null, temp.getBudgetPay().negate(), payMemo,
                            PassengerAccount.OPERATING_SYS, ptype, order.getId(),
                            order.getOrderNo(),
                            PassengerAccount.ORDER_TYPE_ZHUANCHE, null, true, true);
                    } else if (passenger.getType().equals(Passenger.TYPE_ENTERPRISE)) {
                        Enterprise enterprise = memberService
                            .findOneEnterprise(passenger.getEnterprise_id());
                        if (null != enterprise) {
                            memberService
                                .moneyEnterprise(enterprise, temp.getBudgetPay().negate(), payMemo,
                                    PassengerAccount.OPERATING_SYS, ptype, order.getId(),
                                    order.getOrderNo(),
                                    PassengerAccount.ORDER_TYPE_ZHUANCHE, null, true, true);
                        }
                    }
                }
            }
            ResultTransport instance = ResultTransport.getErrorBy(ErrorConstantV4.SUCCESS);
            instance.setData(map);
            return instance;
        } else {
            OrderTemp temp = zhuancheService.findOneTemp(orderGroupId);
            if (null == temp) {
                return ResultTransport.getErrorBy(ErrorConstantV4.ORDER_NOT_EXISTS_ERROR);
            }
            if (temp.isTreatment()) {
                return ResultTransport.getErrorBy(ErrorConstantV4.ALREADY_PAY);
            }
            Passenger passenger = memberService.findOnePassenger(passengerId);
            if (null == passenger) {
                return ResultTransport.getErrorBy(ErrorConstantV4.PASSENGER_NOT_EXISTS);
            }
            if ("sign".equals(payType)) {
                if (!passenger.isAllowOverdraw()) {
                    return ResultTransport.getErrorBy(ErrorConstantV4.PASSENGER_NOT_ALLOW_SIGN);
                }
            } else if ("balance".equals(payType)) {
                if (passenger.getType().equals(Passenger.TYPE_PASSENGER)) {
                    if (passenger.getDrawMoney().doubleValue() < temp.getBudgetPay()
                        .doubleValue()) {
                        return ResultTransport
                            .getErrorBy(ErrorConstantV4.PASSENGER_MONEY_NOT_ENOUGH);
                    }
                } else if (passenger.getType().equals(Passenger.TYPE_ENTERPRISE)) {
                    Enterprise enterprise = memberService
                        .findOneEnterprise(passenger.getEnterprise_id());
                    if (enterprise.getDrawMoney().doubleValue() < temp.getBudgetPay()
                        .doubleValue()) {
                        return ResultTransport
                            .getErrorBy(ErrorConstantV4.PASSENGER_MONEY_NOT_ENOUGH);
                    }
                }
            }
            PayTypeDetails prePayType = null;
            Coupon coupon = null;
            if (null != temp.getCouponId()) {
                coupon = couponService.findOne(temp.getCouponId());
            }
            if (null != coupon) {
                if ("sign".equals(payType)) {
                    prePayType = Order.PayTypeDetails.coupon_sign;
                } else if ("balance".equals(payType)) {
                    prePayType = Order.PayTypeDetails.coupon_balance;
                }
            } else {
                if ("sign".equals(payType)) {
                    prePayType = Order.PayTypeDetails.sign;
                } else if ("balance".equals(payType)) {
                    prePayType = Order.PayTypeDetails.balance;
                }
            }
            Order order = zhuancheService.tempToForeverV4up(temp.getId(), prePayType, coupon);
            if (null != order) {
                // 客户减钱，客户消费记录
                PassengerAccount.PayType ptype = null;
                String payMemo = "";
                if ("sign".equals(payType)) {
                    ptype = PassengerAccount.PayType.PAYTYPE_SIGN;
                    payMemo += "订单【" + order.getOrderNo() + "】预付费使用签单支付"
                        + temp.getBudgetPay().setScale(2, BigDecimal.ROUND_HALF_UP).toString()
                        + "元。";
                } else if ("balance".equals(payType)) {
                    ptype = PassengerAccount.PayType.PAYTYPE_BALANCE;
                    payMemo += "订单【" + order.getOrderNo() + "】预付费使用余额支付"
                        + temp.getBudgetPay().setScale(2, BigDecimal.ROUND_HALF_UP).toString()
                        + "元。";
                }
                if (null != coupon) {
                    if (coupon.getCouponRule().getType().equals(CouponRule.TYPE_DEDUCTION)) {
                        payMemo += "并且使用了" + coupon.getCouponRule().getMoney() + "元优惠券。";
                    } else if (coupon.getCouponRule().getType().equals(CouponRule.TYPE_DISCOUNT)) {
                        payMemo += "并且使用了" + coupon.getCouponRule().getDiscount() + "折优惠券。";
                    }
                }
                if (passenger.getType().equals(Passenger.TYPE_PASSENGER)) {
                    memberService.money(passenger, null, temp.getBudgetPay().negate(), payMemo,
                        PassengerAccount.OPERATING_SYS, ptype, order.getId(), order.getOrderNo(),
                        PassengerAccount.ORDER_TYPE_ZHUANCHE, null, true, true);
                } else if (passenger.getType().equals(Passenger.TYPE_ENTERPRISE)) {
                    Enterprise enterprise = memberService
                        .findOneEnterprise(passenger.getEnterprise_id());
                    if (null != enterprise) {
                        memberService
                            .moneyEnterprise(enterprise, temp.getBudgetPay().negate(), payMemo,
                                PassengerAccount.OPERATING_SYS, ptype, order.getId(),
                                order.getOrderNo(),
                                PassengerAccount.ORDER_TYPE_ZHUANCHE, null, true, true);
                    }
                }

                ResultTransport instance = ResultTransport.getErrorBy(ErrorConstantV4.SUCCESS);
                instance.setData(map);
                return instance;
            } else {
                return ResultTransport.getErrorBy(ErrorConstantV4.SERVER_ERROR);
            }
        }
    }

    /**
     * 银联支付.
     *
     * @throws IOException
     */
    @RequestMapping(value = "unionpay/prepay")
    public @ResponseBody
    ResultTransport unionpayPreDoPost(HttpServletResponse resp,
        HttpServletRequest req, Long orderGroupId, BigDecimal txnAmt, String groupType)
        throws IOException {

        Setting setting = settingUtils.get();
        // 从classpath加载acp_sdk.properties文件
        SDKConfig.getConfig().loadPropertiesFromSrc(setting);

        String orderId = DemoBase.getOrderId();
        int money = txnAmt.multiply(new BigDecimal(100))
            .intValue(); // txnAmt以'元'为单位,乘以100以'分'为单位传给银联
        String txnTime = DemoBase.getCurrentTime(); // 交易时间
        String merId = setting.getMerId(); // 获取商户号
        Map<String, String> contentData = new HashMap<String, String>();

        /*** 银联全渠道系统，产品参数，除了encoding自行选择外其他不需修改 ***/
        contentData.put("version", "5.1.0"); // 版本号 全渠道默认值
        contentData.put("encoding", "UTF-8"); // 字符集编码 可以使用UTF-8,GBK两种方式
        contentData.put("signMethod", "01"); // 签名方法
        contentData.put("txnType", "01"); // 交易类型 01:消费
        contentData.put("txnSubType", "01"); // 交易子类 01：消费
        contentData.put("bizType", "000201"); // 填写000201
        contentData.put("channelType", "08"); // 渠道类型 08手机

        /*** 商户接入参数 ***/
        contentData.put("merId", merId); // 商户号码，请改成自己申请的商户号或者open上注册得来的777商户号测试
        contentData.put("accessType", "0"); // 接入类型，商户接入填0 ，不需修改（0：直连商户， 1： 收单机构
        // 2：平台商户）
        contentData.put("orderId", orderId); // 商户订单号，8-40位数字字母，不能含“-”或“_”，可以自行定制规则
        contentData.put("txnTime", txnTime); // 订单发送时间，取系统时间，格式为YYYYMMDDhhmmss，必须取当前时间，否则会报txnTime无效
        contentData.put("accType", "01"); // 账号类型 01：银行卡02：存折03：IC卡帐号类型(卡介质)
        contentData.put("txnAmt", String.valueOf(money)); // 交易金额 单位为分，不能带小数点
        contentData.put("currencyCode", "156"); // 境内商户固定 156 人民币

        // 请求方保留域，
        // 透传字段，查询、通知、对账文件中均会原样出现，如有需要请启用并修改自己希望透传的数据。
        // 出现部分特殊字符时可能影响解析，请按下面建议的方式填写：
        // 1. 如果能确定内容不会出现&={}[]"'等符号时，可以直接填写数据，建议的方法如下。
        String out_trade_no = "zhuanche_prepay_" + orderGroupId + "_" + groupType;
        // 2. 内容可能出现&={}[]"'符号时：
        // 1) 如果需要对账文件里能显示，可将字符替换成全角＆＝｛｝【】“‘字符（自己写代码，此处不演示）；
        // 2) 如果对账文件没有显示要求，可做一下base64（如下）。
        // 注意控制数据长度，实际传输的数据长度不能超过1024位。
        // 查询、通知等接口解析时使用new String(Base64.decodeBase64(reqReserved),
        // DemoBase.encoding);解base64后再对数据做后续解析。
        // contentData.put("reqReserved",
        // Base64.encodeBase64String(out_trade_no.toString().getBytes("UTF-8")));
        contentData.put("reqReserved", out_trade_no);
        // 后台通知地址（需设置为外网能访问 http
        // https均可），支付成功后银联会自动将异步通知报文post到商户上送的该地址，【支付失败的交易银联不会发送后台通知】
        // 后台通知参数详见open.unionpay.com帮助中心 下载 产品接口规范 网关支付产品接口规范 消费交易 商户通知
        // 注意:1.需设置为外网能访问，否则收不到通知 2.http https均可 3.收单后台通知后需要10秒内返回http200或302状态码
        // 4.如果银联通知服务器发送通知后10秒内未收到返回状态码或者应答码非http200或302，那么银联会间隔一段时间再次发送。总共发送5次，银联后续间隔1、2、4、5
        // 分钟后会再次通知。
        // 5.后台通知地址如果上送了带有？的参数，例如：http://abc/web?a=b&c=d
        // 在后台通知处理程序验证签名之前需要编写逻辑将这些字段去掉再验签，否则将会验签失败
        String backUrl = "";
        if (setting.getWebUrl().endsWith("/")) {
            backUrl = setting.getWebUrl() + "api/zhuanche/v4up/unionpay/notify";
        } else {
            backUrl = setting.getWebUrl() + "/" + "api/zhuanche/v4up/unionpay/notify";
        }
        contentData.put("backUrl", backUrl);

        /** 对请求参数进行签名并发送http post请求，接收同步应答报文 **/
        Map<String, String> reqData = AcpService.sign(contentData,
            DemoBase.encoding); // 报文中certId,signature的值是在signData方法中获取并自动赋值的，只要证书配置正确即可。
        String requestAppUrl = SDKConfig.getConfig()
            .getAppRequestUrl(); // 交易请求url从配置文件读取对应属性文件acp_sdk.properties中的
        // acpsdk.backTransUrl
        Map<String, String> rspData = AcpService.post(reqData, requestAppUrl,
            DemoBase.encoding); // 发送请求报文并接受同步应答（默认连接超时时间30秒，读取返回结果超时时间30秒）;这里调用signData之后，调用submitUrl之前不能对submitFromData中的键值对做任何修改，如果修改会导致验签不通过

        /** 对应答码的处理，请根据您的业务逻辑来编写程序,以下应答码处理逻辑仅供参考-------------> **/
        // 应答码规范参考open.unionpay.com帮助中心 下载 产品接口规范 《平台接入接口规范-第5部分-附录》
        if (!rspData.isEmpty()) {
            if (AcpService.validate(rspData, DemoBase.encoding)) {
                LogUtil.writeLog("验证签名成功");
                String respCode = rspData.get("respCode");
                if (("00").equals(respCode)) {
                    // 成功,获取tn交易流水号
                    String tn = rspData.get("tn");
                    ResultTransport instance = ResultTransport.getErrorBy(ErrorConstantV4.SUCCESS);
                    instance.setData(tn);
                    return instance;
                } else {
                    // 其他应答码为失败请排查原因或做失败处理
                    return ResultTransport.getErrorBy(ErrorConstantV4.SERVER_ERROR);
                }
            } else {
                LogUtil.writeErrorLog("验证签名失败");
                return ResultTransport.getErrorBy(ErrorConstantV4.SERVER_ERROR);
            }
        } else {
            // 未返回正确的http状态
            LogUtil.writeErrorLog("未获取到返回报文或返回http状态码非200");
            return ResultTransport.getErrorBy(ErrorConstantV4.SERVER_ERROR);
        }
    }

    /**
     * 银联支付回调.
     */
    @RequestMapping(value = "unionpay/notify")
    public synchronized @ResponseBody
    void unionpayNotify(HttpServletResponse resp,
        HttpServletRequest req) throws Exception {

        LogUtil.writeLog("BackRcvResponse接收后台通知开始");

        String encoding = req.getParameter(SDKConstants.param_encoding);
        // 获取银联通知服务器发送的后台通知参数
        Map<String, String> reqParam = getAllRequestParam(req);

        LogUtil.printRequestLog(reqParam);

        Map<String, String> valideData = null;
        if (null != reqParam && !reqParam.isEmpty()) {
            Iterator<Entry<String, String>> it = reqParam.entrySet().iterator();
            valideData = new HashMap<String, String>(reqParam.size());
            while (it.hasNext()) {
                Entry<String, String> e = it.next();
                String key = (String) e.getKey();
                String value = (String) e.getValue();

                valideData.put(key, value);
            }
        }

        // 重要！验证签名前不要修改reqParam中的键值对的内容，否则会验签不过
        if (!AcpService.validate(valideData, encoding)) {
            LogUtil.writeLog("验证签名结果[失败].");
            // 验签失败，需解决验签问题
        } else {
            LogUtil.writeLog("验证签名结果[成功].");
            // 【注：为了安全验签成功才应该写商户的成功处理逻辑】交易成功，更新商户订单状态

            LogUtil.writeLog("后台通知的数据orderId:" + valideData.get("orderId"));
            String respCode = valideData.get("respCode");

            if ("00".equals(respCode)) {
                String out_trade_no = valideData.get("reqReserved"); // 获取后台通知的数据，其他字段也可用类似方式获取
                String txnAmt = valideData.get("txnAmt");

                // 判断respCode=00、A6后，对涉及资金类的交易，请再发起查询接口查询，确定交易成功后更新数据库。

                String groupType = "";
                if (StringUtils.isNotBlank(out_trade_no)) {
                    String[] split = out_trade_no.split("_");
                    out_trade_no = split[0] + "_" + split[1] + "_" + split[2];
                    groupType = split[3];
                }
                // 调用专车系统支付成功,把临时表的订单信息新增到真实表中
                if ("group".equals(groupType)) {// 一组订单支付完成
                    Long groupId = Long.valueOf(out_trade_no.split("_")[2]);
                    List<OrderTemp> list = zhuancheService.queryByGroupId(groupId);
                    for (OrderTemp temp : list) {
                        Coupon coupon = null;
                        if (null != temp.getCouponId()) {
                            coupon = couponService.findOne(temp.getCouponId());
                        }
                        PayTypeDetails payType = PayTypeDetails.unionpay;
                        if (null != coupon) {
                            payType = Order.PayTypeDetails.coupon_unionpay;
                        }
                        Order order = zhuancheService
                            .tempToForeverV4up(temp.getId(), payType, coupon);
                        if (null != order) {// 客户消费记录
                            Passenger passenger = memberService
                                .findOnePassenger(order.getPassengerId());
                            String payMemo = "订单【" + order.getOrderNo() + "】预付费使用银联支付"
                                + temp.getBudgetPay().setScale(2, BigDecimal.ROUND_HALF_UP)
                                .toString() + "元。";
                            if (null != coupon) {
                                if (coupon.getCouponRule().getType()
                                    .equals(CouponRule.TYPE_DEDUCTION)) {
                                    payMemo +=
                                        "并且使用了" + coupon.getCouponRule().getMoney() + "元优惠券。";
                                } else if (coupon.getCouponRule().getType()
                                    .equals(CouponRule.TYPE_DISCOUNT)) {
                                    payMemo +=
                                        "并且使用了" + coupon.getCouponRule().getDiscount() + "折优惠券。";
                                }
                            }
                            if (passenger.getType().equals(Passenger.TYPE_PASSENGER)) {
                                memberService
                                    .money(passenger, null, temp.getBudgetPay().negate(), payMemo,
                                        PassengerAccount.OPERATING_SYS,
                                        PassengerAccount.PayType.PAYTYPE_UNIONPAY,
                                        order.getId(), order.getOrderNo(),
                                        PassengerAccount.ORDER_TYPE_ZHUANCHE, null,
                                        false, false);
                            } else if (passenger.getType().equals(Passenger.TYPE_ENTERPRISE)) {
                                Enterprise enterprise = memberService.findOneEnterprise(passenger
                                    .getEnterprise_id());
                                if (null != enterprise) {
                                    memberService
                                        .moneyEnterprise(enterprise, temp.getBudgetPay().negate(),
                                            payMemo,
                                            PassengerAccount.OPERATING_SYS,
                                            PassengerAccount.PayType.PAYTYPE_UNIONPAY,
                                            order.getId(), order.getOrderNo(),
                                            PassengerAccount.ORDER_TYPE_ZHUANCHE,
                                            null, false, false);
                                }
                            }
                        }
                    }
                } else {
                    Long orderId = Long.valueOf(out_trade_no.split("_")[2]);
                    OrderTemp temp = zhuancheService.findOneTemp(orderId);
                    if (temp.isTreatment()) {
                        resp.getWriter().print("ok");
                    }
                    Coupon coupon = null;
                    if (null != temp.getCouponId()) {
                        coupon = couponService.findOne(temp.getCouponId());
                    }
                    PayTypeDetails payType = PayTypeDetails.unionpay;
                    if (null != coupon) {
                        payType = Order.PayTypeDetails.coupon_unionpay;
                    }
                    Order order = zhuancheService.tempToForeverV4up(orderId, payType, coupon);
                    if (null != order) {
                        // 客户消费记录
                        Passenger passenger = memberService
                            .findOnePassenger(order.getPassengerId());
                        String payMemo = "订单【" + order.getOrderNo() + "】预付费使用银联支付"
                            + temp.getBudgetPay().setScale(2, BigDecimal.ROUND_HALF_UP).toString()
                            + "元。";
                        if (null != coupon) {
                            if (coupon.getCouponRule().getType()
                                .equals(CouponRule.TYPE_DEDUCTION)) {
                                payMemo += "并且使用了" + coupon.getCouponRule().getMoney() + "元优惠券。";
                            } else if (coupon.getCouponRule().getType()
                                .equals(CouponRule.TYPE_DISCOUNT)) {
                                payMemo += "并且使用了" + coupon.getCouponRule().getDiscount() + "折优惠券。";
                            }
                        }
                        if (passenger.getType().equals(Passenger.TYPE_PASSENGER)) {
                            memberService
                                .money(passenger, null, temp.getBudgetPay().negate(), payMemo,
                                    PassengerAccount.OPERATING_SYS,
                                    PassengerAccount.PayType.PAYTYPE_UNIONPAY,
                                    order.getId(), order.getOrderNo(),
                                    PassengerAccount.ORDER_TYPE_ZHUANCHE, null,
                                    false, false);
                        } else if (passenger.getType().equals(Passenger.TYPE_ENTERPRISE)) {
                            Enterprise enterprise = memberService
                                .findOneEnterprise(passenger.getEnterprise_id());
                            if (null != enterprise) {
                                memberService
                                    .moneyEnterprise(enterprise, temp.getBudgetPay().negate(),
                                        payMemo,
                                        PassengerAccount.OPERATING_SYS,
                                        PassengerAccount.PayType.PAYTYPE_UNIONPAY,
                                        order.getId(), order.getOrderNo(),
                                        PassengerAccount.ORDER_TYPE_ZHUANCHE, null,
                                        false, false);
                            }
                        }
                        resp.getWriter().print("ok");
                    } else {
                        resp.getWriter().print("ok");
                    }
                }
            }
        }
        LogUtil.writeLog("BackRcvResponse接收后台通知结束");
        // 返回给银联服务器http 200 状态码
        resp.getWriter().print("ok");
    }

    /**
     * 查询银联支付交易接口.
     */
    @RequestMapping(value = "unionpay/query")
    public void unionPayQuery(HttpServletRequest req, HttpServletResponse resp, String orderId,
        String txnTime) throws Exception {

        Setting setting = settingUtils.get();
        SDKConfig.getConfig().loadPropertiesFromSrc(setting);// 从classpath加载acp_sdk.properties文件

        String merId = setting.getMerId();

        Map<String, String> data = new HashMap<String, String>();

        /*** 银联全渠道系统，产品参数，除了encoding自行选择外其他不需修改 ***/
        data.put("version", DemoBase.version); // 版本号
        data.put("encoding", DemoBase.encoding); // 字符集编码 可以使用UTF-8,GBK两种方式
        data.put("signMethod", SDKConfig.getConfig().getSignMethod()); // 签名方法
        data.put("txnType", "00"); // 交易类型 00-默认
        data.put("txnSubType", "00"); // 交易子类型 默认00
        data.put("bizType", "000201"); // 业务类型

        /*** 商户接入参数 ***/
        data.put("merId", merId); // 商户号码，请改成自己申请的商户号或者open上注册得来的777商户号测试
        data.put("accessType", "0"); // 接入类型，商户接入固定填0，不需修改

        /*** 要调通交易以下字段必须修改 ***/
        data.put("orderId", orderId); // ****商户订单号，每次发交易测试需修改为被查询的交易的订单号
        data.put("txnTime", txnTime); // ****订单发送时间，每次发交易测试需修改为被查询的交易的订单发送时间

        /** 请求参数设置完毕，以下对请求参数进行签名并发送http post请求，接收同步应答报文-------------> **/

        Map<String, String> reqData = AcpService.sign(data,
            DemoBase.encoding); // 报文中certId,signature的值是在signData方法中获取并自动赋值的，只要证书配置正确即可。
        String url = SDKConfig.getConfig()
            .getSingleQueryUrl(); // 交易请求url从配置文件读取对应属性文件acp_sdk.properties中的
        // acpsdk.singleQueryUrl
        Map<String, String> rspData = AcpService.post(reqData, url,
            DemoBase.encoding); // 发送请求报文并接受同步应答（默认连接超时时间30秒，读取返回结果超时时间30秒）;这里调用signData之后，调用submitUrl之前不能对submitFromData中的键值对做任何修改，如果修改会导致验签不通过

        /** 对应答码的处理，请根据您的业务逻辑来编写程序,以下应答码处理逻辑仅供参考-------------> **/
        // 应答码规范参考open.unionpay.com帮助中心 下载 产品接口规范 《平台接入接口规范-第5部分-附录》
        if (!rspData.isEmpty()) {
            if (AcpService.validate(rspData, DemoBase.encoding)) {
                LogUtil.writeLog("验证签名成功");
                if (("00").equals(rspData.get("respCode"))) {// 如果查询交易成功
                    String origRespCode = rspData.get("origRespCode");
                    if (("00").equals(origRespCode)) {
                        // 交易成功，更新商户订单状态
                    } else if (("03").equals(origRespCode) || ("04").equals(origRespCode)
                        || ("05").equals(origRespCode)) {
                        // 订单处理中或交易状态未明，需稍后发起交易状态查询交易 【如果最终尚未确定交易是否成功请以对账文件为准】
                    } else {
                        // 其他应答码为交易失败
                    }
                } else if (("34").equals(rspData.get("respCode"))) {
                    // 订单不存在，可认为交易状态未明，需要稍后发起交易状态查询，或依据对账结果为准
                } else {// 查询交易本身失败，如应答码10/11检查查询报文是否正确
                }
            } else {
                LogUtil.writeErrorLog("验证签名失败");
            }
        } else {
            // 未返回正确的http状态
            LogUtil.writeErrorLog("未获取到返回报文或返回http状态码非200");
        }

        String reqMessage = DemoBase.genHtmlResult(reqData);
        String rspMessage = DemoBase.genHtmlResult(rspData);
        resp.getWriter().write(
            "交易状态查询交易</br>请求报文:<br/>" + reqMessage + "<br/>" + "应答报文:</br>" + rspMessage + "");
    }

    /**
     * 翼支付预先支付
     *
     * @param request 请求对象
     * @param orderId 订单号
     * @return
     * @throws Exception
     */
    @ResponseBody
    @RequestMapping("bestpay/prepay")
    public synchronized ResultTransport bestPayByPrepay(HttpServletResponse response,
        HttpServletRequest request, Long orderGroupId, Double amount, String groupType,
        Long memberId)
        throws Exception {

        ResultTransport transport = null;
        try {
            // 获取系统设置
            Setting setting = settingUtils.get();
            String callBackUrl = setting.getWebUrl() + "/api/zhuanche/v4up/bestpay/notify";
            String createUrl = "https://webpaywg.bestpay.com.cn/order.action";

            // 获取商户信息
            String mch_id = setting.getMerchantId();
            String mch_key = setting.getMerKey();
            String mch_pwd = setting.getMchPwd();
            String riskInfo = setting.getRiskcontrolinfo();
            String attach_order_id =
                "zhuanche_prepay_" + orderGroupId + "_" + groupType; // 商户订单号,这里作为附加信息，因为订单不能个包含特殊字符
            String body = "专车预先支付充值";

            // 使用随机数来作为订单流水号
            String currTime = TenpayUtil.getCurrTime();
            String strTime = currTime.substring(8, currTime.length()); // 8位日期
            String strRandom = TenpayUtil.buildRandom(6) + ""; // 四位随机数
            String strReq = strTime + strRandom; // 10位序列号,可以自行调整

            BigDecimal money = new BigDecimal(amount); // 预支付的金额
            Passenger passenger = memberService.findOnePassenger(memberId);
            String phone = passenger.getPhone();

            // 格式化金额0.00
            DecimalFormat myformat = new java.text.DecimalFormat("0.00");
            String money_ = myformat.format(money);

            // 订单模型
            String total_fee = String
                .valueOf(money.multiply(new BigDecimal(100)).intValue()); // 元转分
            BestPayOrderModel orderModel = new BestPayOrderModel();
            orderModel.setATTACH(attach_order_id);
            orderModel.setCITYCODE("");
            orderModel.setDIVDETAILS("");
            orderModel.setENCODE("");
            orderModel.setENCODETYPE("1");
            orderModel.setKEY(mch_key);
            orderModel.setLOGINNO("");
            orderModel.setMERCHANTID(mch_id);
            orderModel.setORDERAMT(total_fee); // 分
            orderModel.setORDERCCY("RMB");
            orderModel.setORDERREQTIME(currTime);
            orderModel.setORDERREQTRANSEQ(strReq);
            orderModel.setORDERSEQ(strReq);
            orderModel.setPRODUCTDESC(body);
            orderModel.setPRODUCTID("04");
            orderModel.setPROVINCECODE("");
            orderModel.setRISKCONTROLINFO(riskInfo);
            orderModel.setSERVICECODE("05");
            orderModel.setSESSIONKEY("");
            orderModel.setSUBMERCHANTID("");
            orderModel.setTRANSCODE("01");
            boolean rs = BestPayCreateOrder.createByApp(createUrl, orderModel);

            // 下单失败
            if (!rs) {
                return ResultTransport.getErrorBy(ErrorConstantV4.BESTPAY_APP_CREATE_ORDER_ERR);
            }

            // 签名参数
            StringBuffer md5Buffer = new StringBuffer();
            md5Buffer.append("SERVICE=").append("mobile.security.pay").append("&MERCHANTID=")
                .append(mch_id).append("&MERCHANTPWD=").append(mch_pwd).append("&SUBMERCHANTID=")
                .append("").append("&BACKMERCHANTURL=").append(callBackUrl).append("&ORDERSEQ=")
                .append(strReq).append("&ORDERREQTRANSEQ=").append(strReq).append("&ORDERTIME=")
                .append(currTime).append("&ORDERVALIDITYTIME=").append("").append("&CURTYPE=")
                .append("RMB").append("&ORDERAMOUNT=").append(money_).append("&SUBJECT=")
                .append(body)
                .append("&PRODUCTID=").append("04").append("&PRODUCTDESC=").append(body)
                .append("&CUSTOMERID=").append(phone).append("&SWTICHACC=").append("true")
                .append("&KEY=").append(mch_key);

            // 签名
            logger.info("MAC(MD5)--before--String：" + md5Buffer.toString());
            String sign = CryptTool.md5Digest(md5Buffer.toString());
            logger.info("MAC(MD5)--after--String:" + sign);

            // 拼接返回数据串
            StringBuffer paramsBuffer = new StringBuffer();
            paramsBuffer
                .append("SERVICE=")
                .append("mobile.security.pay")
                .append("&MERCHANTID=")
                .append(mch_id)
                // 签约商户号
                .append("&MERCHANTPWD=").append(mch_pwd).append("&SUBMERCHANTID=").append("")
                .append("&BACKMERCHANTURL=").append(callBackUrl).append("&SIGNTYPE=").append("MD5")
                .append("&SIGN=").append(sign).append("&ORDERSEQ=").append(strReq)
                .append("&ORDERREQTRANSEQ=").append(strReq).append("&ORDERTIME=").append(currTime)
                .append("&ORDERVALIDITYTIME=").append("").append("&ORDERAMOUNT=").append(money_)
                .append("&CURTYPE=").append("RMB").append("&PRODUCTID=").append("04")
                .append("&PRODUCTDESC=").append(body).append("&PRODUCTAMOUNT=").append(money_)
                .append("&ATTACHAMOUNT=").append("0.00").append("&ATTACH=").append(attach_order_id)
                .append("&DIVDETAILS=").append("").append("&ACCOUNTID=").append("")
                .append("&CUSTOMERID=").append(phone).append("&USERIP=").append("")
                .append("&BUSITYPE=")
                .append("04").append("&SWTICHACC=").append("true").append("&SUBJECT=").append(body);

            // 返回数据
            String params = paramsBuffer.toString();
            transport = ResultTransport.getErrorBy(ErrorConstantV4.SUCCESS);
            transport.setData(params);
            return transport;
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("api zhuanche bestpayPrepay 专车支付 error: {}", e);
            return ResultTransport.getErrorBy(ErrorConstantV4.SERVER_ERROR);
        }

    }

    /**
     * 翼支付预支付回调
     *
     * @param request
     */
    @RequestMapping("bestpay/notify")
    public synchronized @ResponseBody
    String bestPayNotify(HttpServletRequest request,
        HttpServletResponse response) {
        try {
            // 准备
            request.setCharacterEncoding("UTF-8");
            response.setCharacterEncoding("UTF-8");
            PrintWriter out = response.getWriter();

            // 获取回调数据，注释部分为没有使用的部分数据，其所代表的意义详见翼支付APP文档
            String UPTRANSEQ = request.getParameter("UPTRANSEQ");
            String MERCHANTID = request.getParameter("MERCHANTID");
            String TRANDATE = request.getParameter("TRANDATE");
            String RETNCODE = request.getParameter("RETNCODE");
            String RETNINFO = request.getParameter("RETNINFO");
            // String ORDERREQTRANSEQ = request.getParameter("ORDERREQTRANSEQ");
            String ORDERSEQ = request.getParameter("ORDERSEQ");
            String ORDERAMOUNT = request.getParameter("ORDERAMOUNT");
            // String PRODUCTAMOUNT = request.getParameter("PRODUCTAMOUNT");
            // String ATTACHAMOUNT = request.getParameter("ATTACHAMOUNT");
            // String CURTYPE = request.getParameter("CURTYPE");
            // String ENCODETYPE = request.getParameter("ENCODETYPE");
            // String BANKID = request.getParameter("BANKID");
            String ATTACH = request.getParameter("ATTACH");
            // String UPREQTRANSEQ = request.getParameter("UPREQTRANSEQ");
            // String UPBANKTRANSEQ = request.getParameter("UPBANKTRANSEQ");
            // String PRODUCTNO = request.getParameter("PRODUCTNO");
            String SIGN = request.getParameter("SIGN");

            // 验证签名
            Setting setting = settingUtils.get();
            String key = setting.getMerKey();
            String signStr = "UPTRANSEQ=" + UPTRANSEQ + "&MERCHANTID=" + MERCHANTID + "&ORDERSEQ="
                + ORDERSEQ + "&ORDERAMOUNT=" + ORDERAMOUNT + "&RETNCODE=" + RETNCODE + "&RETNINFO="
                + RETNINFO + "&TRANDATE=" + TRANDATE + "&KEY=" + key;
            String localSign = CryptTool.md5Digest(signStr);

            // 验签失败
            if (!localSign.equals(SIGN)) {
                out.write("UPTRANSEQ_" + UPTRANSEQ);
                logger.info("支付回调，验签失败！");
                return "FAIL";
            }
            String groupType = ATTACH.split("_")[3];

            // 验签成功，看是否支付成功("0000为成功，其他均为失败")
            if (RETNCODE.equals("0000")) {
                if ("group".equals(groupType)) {// 一组订单支付完成
                    // 一组订单支付完成
                    Long groupId = Long.valueOf(ATTACH.split("_")[2]);
                    List<OrderTemp> list = zhuancheService.queryByGroupId(groupId);
                    for (OrderTemp temp : list) {
                        Coupon coupon = null;
                        if (null != temp.getCouponId()) {
                            coupon = couponService.findOne(temp.getCouponId());
                        }
                        PayTypeDetails payType = PayTypeDetails.bestpay;
                        if (null != coupon) {
                            payType = Order.PayTypeDetails.coupon_bestpay;
                        }
                        Order order = zhuancheService
                            .tempToForeverV4up(temp.getId(), payType, coupon);
                        if (null != order) {// 客户消费记录
                            Passenger passenger = memberService
                                .findOnePassenger(order.getPassengerId());
                            String payMemo = "订单【" + order.getOrderNo() + "】预付费使用翼支付支付"
                                + temp.getBudgetPay().setScale(2, BigDecimal.ROUND_HALF_UP)
                                .toString() + "元。";
                            if (null != coupon) {
                                if (coupon.getCouponRule().getType()
                                    .equals(CouponRule.TYPE_DEDUCTION)) {
                                    payMemo +=
                                        "并且使用了" + coupon.getCouponRule().getMoney() + "元优惠券。";
                                } else if (coupon.getCouponRule().getType()
                                    .equals(CouponRule.TYPE_DISCOUNT)) {
                                    payMemo +=
                                        "并且使用了" + coupon.getCouponRule().getDiscount() + "折优惠券。";
                                }
                            }
                            if (passenger.getType().equals(Passenger.TYPE_PASSENGER)) {
                                memberService
                                    .money(passenger, null, temp.getBudgetPay().negate(), payMemo,
                                        PassengerAccount.OPERATING_SYS,
                                        PassengerAccount.PayType.PAYTYPE_BESTPAY,
                                        order.getId(), order.getOrderNo(),
                                        PassengerAccount.ORDER_TYPE_ZHUANCHE, null,
                                        false, false);
                            } else if (passenger.getType().equals(Passenger.TYPE_ENTERPRISE)) {
                                Enterprise enterprise = memberService.findOneEnterprise(passenger
                                    .getEnterprise_id());
                                if (null != enterprise) {
                                    memberService
                                        .moneyEnterprise(enterprise, temp.getBudgetPay().negate(),
                                            payMemo,
                                            PassengerAccount.OPERATING_SYS,
                                            PassengerAccount.PayType.PAYTYPE_BESTPAY,
                                            order.getId(), order.getOrderNo(),
                                            PassengerAccount.ORDER_TYPE_ZHUANCHE,
                                            null, false, false);
                                }
                            }
                        }
                    }
                    return "SUCCESS";
                } else {
                    Long orderId = Long.valueOf(ATTACH.split("_")[2]);
                    OrderTemp temp = zhuancheService.findOneTemp(orderId);
                    if (temp.isTreatment()) {
                        // 打印成功信息
                        return "SUCCESS";
                    }
                    Coupon coupon = null;
                    if (null != temp.getCouponId()) {
                        coupon = couponService.findOne(temp.getCouponId());
                    }
                    PayTypeDetails payType = PayTypeDetails.bestpay;
                    if (null != coupon) {
                        payType = Order.PayTypeDetails.coupon_bestpay;
                    }
                    Order order = zhuancheService.tempToForeverV4up(orderId, payType, coupon);
                    if (null != order) {
                        // 客户消费记录
                        Passenger passenger = memberService
                            .findOnePassenger(order.getPassengerId());
                        String payMemo = "订单【" + order.getOrderNo() + "】预付费使用翼支付支付"
                            + temp.getBudgetPay().setScale(2, BigDecimal.ROUND_HALF_UP).toString()
                            + "元。";
                        if (null != coupon) {
                            if (coupon.getCouponRule().getType()
                                .equals(CouponRule.TYPE_DEDUCTION)) {
                                payMemo += "并且使用了" + coupon.getCouponRule().getMoney() + "元优惠券。";
                            } else if (coupon.getCouponRule().getType()
                                .equals(CouponRule.TYPE_DISCOUNT)) {
                                payMemo += "并且使用了" + coupon.getCouponRule().getDiscount() + "折优惠券。";
                            }
                        }
                        if (passenger.getType().equals(Passenger.TYPE_PASSENGER)) {
                            memberService
                                .money(passenger, null, temp.getBudgetPay().negate(), payMemo,
                                    PassengerAccount.OPERATING_SYS,
                                    PassengerAccount.PayType.PAYTYPE_BESTPAY,
                                    order.getId(), order.getOrderNo(),
                                    PassengerAccount.ORDER_TYPE_ZHUANCHE, null,
                                    false, false);
                        } else if (passenger.getType().equals(Passenger.TYPE_ENTERPRISE)) {
                            Enterprise enterprise = memberService
                                .findOneEnterprise(passenger.getEnterprise_id());
                            if (null != enterprise) {
                                memberService
                                    .moneyEnterprise(enterprise, temp.getBudgetPay().negate(),
                                        payMemo,
                                        PassengerAccount.OPERATING_SYS,
                                        PassengerAccount.PayType.PAYTYPE_BESTPAY,
                                        order.getId(), order.getOrderNo(),
                                        PassengerAccount.ORDER_TYPE_ZHUANCHE, null,
                                        false, false);
                            }
                        }
                        return "SUCCESS";
                    } else {
                        return "FAIL";
                    }
                }
            }
            return "FAIL";
        } catch (Exception e) {
            // 异常不返回，以便不丢失支付数据
            e.printStackTrace();
            return "FAIL";
        }
    }

}
